﻿using System;
using System.Windows.Interop;
using Microsoft.Expression.Shapes;
using System.Windows.Controls;
using System.Windows.Media;

namespace Steer
{
    /// <summary>
    /// 机车类
    /// </summary>
    public class Vehicle : Canvas
    {
        protected string _edgeBehavior = WRAP;
        protected double _mass = 1.0;
        protected double _maxSpeed = 10;
        protected Vector2D _postion;
        protected Vector2D _velocity;

        private CompositeTransform _compositeTransform;
        private TransformGroup _transformGroup;

        /// <summary>
        /// 边缘行为
        /// </summary>
        public const string WRAP = "wrap";
        public const string BOUNCE = "bounce";

        public Vehicle()
        {
            _postion = new Vector2D(0, 0);
            _velocity = new Vector2D(0, 0);
            this.Loaded += new System.Windows.RoutedEventHandler(Vehicle_Loaded);
        }

        void Vehicle_Loaded(object sender, System.Windows.RoutedEventArgs e)
        {
            var transformGroup = this.RenderTransform as TransformGroup;
            if (transformGroup == null)
            {
                _transformGroup = new TransformGroup();
                this.RenderTransform = _transformGroup;
                _compositeTransform = new CompositeTransform();
                _transformGroup.Children.Add(_compositeTransform);
            }
        }

        public virtual void update()
        {
            _velocity.truncate(_maxSpeed);
            _postion = _postion.add(_velocity);

            if (_edgeBehavior == WRAP)
            {
                wrap();
            }
            else if (_edgeBehavior == BOUNCE)
            {
                bounce();
            }

            x = position.x;
            y = position.y;
            _compositeTransform.Rotation = _velocity.angle * 180 / Math.PI;
        }

        /// <summary>
        /// 反弹
        /// </summary>
        private void bounce()
        {
            Content stage = App.Current.Host.Content;
            if (position.x > stage.ActualWidth-this.ActualWidth)
            {
                position.x = stage.ActualWidth - this.ActualWidth;
                velocity.x *= -1;
            }
            else if (_postion.x < 0)
            {
                position.x = 0;
                velocity.x *= -1;
            }

            if (position.y > stage.ActualHeight-this.ActualHeight)
            {
                position.y = stage.ActualHeight - this.ActualHeight;
                velocity.y *= -1;
            }
            else if (position.y < 0)
            {
                position.y = 0;
                velocity.y *= -1;
            }
        }

        /// <summary>
        /// 巡游
        /// </summary>
        private void wrap()
        {
            Content stage = App.Current.Host.Content;
            if (position.x > stage.ActualWidth)
            {
                position.x = 0;
            }
            if (position.x < 0)
            {
                position.x = stage.ActualWidth;
            }
            if (position.y > stage.ActualHeight)
            {
                position.y = 0;
            }
            if (position.y < 0)
            {
                position.y = stage.ActualHeight;
            }
        }

        public string edgeBehavior
        {
            get
            {
                return _edgeBehavior;
            }
            set
            {
                _edgeBehavior = value;
            }
        }

        public double mass
        {
            get
            {
                return _mass;
            }
            set
            {
                _mass = value;
            }
        }

        public double maxSpeed
        {
            get
            {
                return _maxSpeed;
            }
            set
            {
                _maxSpeed = value;
            }
        }

        public Vector2D position
        {
            get
            {
                return _postion;
            }
            set
            {
                _postion = value;
                x = _postion.x;
                y = _postion.y;
            }
        }

        public Vector2D velocity
        {
            get
            {
                return _velocity;
            }
            set
            {
                _velocity = value;
            }
        }

        public double x
        {
            get
            {
                return _compositeTransform.TranslateX;
            }
            set
            {
                _compositeTransform.TranslateX = value;
                _postion.x = value;
            }
        }

        public double y
        {
            get
            {
                return _compositeTransform.TranslateY;
            }
            set
            {
                _compositeTransform.TranslateY = value;
                _postion.y = value;
            }
        }
    }
}
